"""
PLC客户端工厂模块

提供统一的PLC客户端创建接口，支持多种厂商的PLC设备
"""

import logging
from typing import Optional, Dict, Any

from .mitsubishi import FX3UModbusClient, FX3UModbusTCPClient
from .siemens import SiemensS7ModbusTCPClient
from .base import BasePLCClient

logger = logging.getLogger(__name__)


def get_plc_client(device_type: str, **kwargs) -> Optional[BasePLCClient]:
    """
    PLC客户端工厂函数.
    
    根据指定的设备类型返回相应的PLC客户端实例.
    
    参数:
        device_type (str): 设备类型.
            'mitsubishi_fx3u_rtu': 三菱FX3U (RTU串口)
            'mitsubishi_fx3u_tcp': 三菱FX3U (TCP)
            'siemens_s7_tcp': 西门子S7 (TCP)
        **kwargs: 客户端初始化所需的参数(如host, port, slave_id等).
        
    返回:
        对应的PLC客户端实例, 或在类型不支持时返回None.
    """
    clients = {
        "mitsubishi_fx3u_rtu": FX3UModbusClient,
        "mitsubishi_fx3u_tcp": FX3UModbusTCPClient,
        "siemens_s7_tcp": SiemensS7ModbusTCPClient,
    }
    
    client_class = clients.get(device_type)
    
    if client_class:
        logger.info(f"创建客户端，类型: {device_type}")
        try:
            return client_class(**kwargs)
        except Exception as e:
            logger.error(f"创建客户端时发生错误: {e}")
            return None
    else:
        logger.error(f"不支持的设备类型: {device_type}")
        return None


def get_supported_devices() -> Dict[str, Dict[str, Any]]:
    """
    获取所有支持的设备类型及其信息
    
    返回:
        Dict: 设备类型信息字典
    """
    return {
        "mitsubishi_fx3u_rtu": {
            "manufacturer": "三菱 (Mitsubishi)",
            "model": "FX3U",
            "communication": "Modbus RTU (串口)",
            "description": "三菱FX3U系列PLC，通过串口进行Modbus RTU通信",
            "parameters": ["port", "baudrate", "parity", "slave_id"]
        },
        "mitsubishi_fx3u_tcp": {
            "manufacturer": "三菱 (Mitsubishi)",
            "model": "FX3U",
            "communication": "Modbus TCP",
            "description": "三菱FX3U系列PLC，通过以太网进行Modbus TCP通信",
            "parameters": ["host", "port", "timeout", "slave_id"]
        },
        "siemens_s7_tcp": {
            "manufacturer": "西门子 (Siemens)",
            "model": "S7",
            "communication": "Modbus TCP",
            "description": "西门子S7系列PLC，通过以太网进行Modbus TCP通信",
            "parameters": ["host", "port", "timeout", "slave_id"]
        }
    }


def validate_client_parameters(device_type: str, **kwargs) -> tuple[bool, str]:
    """
    验证PLC客户端参数
    
    参数:
        device_type (str): 设备类型
        **kwargs: 参数字典
        
    返回:
        tuple: (是否有效, 错误信息)
    """
    supported_devices = get_supported_devices()
    
    if device_type not in supported_devices:
        return False, f"不支持的设备类型: {device_type}"
    
    device_info = supported_devices[device_type]
    required_params = device_info["parameters"]
    
    # 检查必需参数
    missing_params = []
    for param in required_params:
        if param not in kwargs:
            # 一些参数有默认值，不强制要求
            if param in ["timeout", "slave_id", "parity", "baudrate"]:
                continue
            missing_params.append(param)
    
    if missing_params:
        return False, f"缺少必需参数: {', '.join(missing_params)}"
    
    # 参数类型检查
    if "port" in kwargs and device_type.endswith("_tcp"):
        # TCP端口检查
        try:
            port = int(kwargs["port"])
            if not (1 <= port <= 65535):
                return False, "TCP端口必须在1-65535范围内"
        except (ValueError, TypeError):
            return False, "TCP端口必须是数字"
    
    if "baudrate" in kwargs:
        # 波特率检查
        valid_baudrates = [9600, 19200, 38400, 57600, 115200]
        try:
            baudrate = int(kwargs["baudrate"])
            if baudrate not in valid_baudrates:
                return False, f"波特率必须是以下值之一: {valid_baudrates}"
        except (ValueError, TypeError):
            return False, "波特率必须是数字"
    
    if "slave_id" in kwargs:
        # 从站地址检查
        try:
            slave_id = int(kwargs["slave_id"])
            if not (1 <= slave_id <= 255):
                return False, "从站地址必须在1-255范围内"
        except (ValueError, TypeError):
            return False, "从站地址必须是数字"
    
    return True, ""
